<template>
  <div :class="{ 'basic-input-form': title }">
    <div class="input-box" v-show="title">
      <div class="flex-space pa-b-16">
        <div>
          <span>
            <el-link
              :underline="false"
              class="link-btn"
              @click="nodeDta.isInputFold = !nodeDta.isInputFold"
            >
              <el-icon v-show="!nodeDta.isInputFold"><ArrowDown /></el-icon>
              <el-icon v-show="nodeDta.isInputFold"><ArrowRight /></el-icon>
            </el-link>
          </span>
          <span>{{ props.title }}</span>
        </div>
        <div>
          <el-link :underline="false" type="primary" @click="addInputVariable" v-show="isAddBtn">
            <el-icon><Plus /></el-icon>
          </el-link>
        </div>
      </div>
    </div>
    <el-form
      v-show="!nodeDta.isInputFold"
      ref="RuleFormRef"
      :model="nodeDta"
      :rules="rules"
      label-width="50"
      label-position="top"
      class="custom-form"
    >
      <div v-for="(item, index) in nodeDta.input_variables" :key="item.uuId" class="form-box">
        <template
          v-if="
            (props.formType === 'iterationInput' && index !== 0) ||
            props.formType !== 'iterationInput'
          "
        >
          <el-form-item
            style="margin-right: 20px; width: 160px"
            :label="item.variableLabel ? item.variableLabel : '变量名'"
            :prop="'input_variables.' + index + '.variable'"
            :rules="[
              {
                required:
                  item.is_required === true || item.is_required === false ? item.is_required : true,
                message: `请输入${item.variableLabel ? item.variableLabel : '变量名'}`,
                trigger: 'change'
              },
              {
                min: 1,
                max: 100,
                message: `${item.variableLabel ? item.variableLabel : '变量名'}为1-100个字符`,
                trigger: 'change'
              },
              {
                validator: repeatValidator,
                variableItem: item,
                input_variables: nodeDta.input_variables,
                message1: item.variableLabel ? item.variableLabel : '变量名',
                trigger: 'blur'
              }
            ]"
          >
            <el-input
              v-model.trim="item.variable"
              placeholder="请输入参数名"
              :disabled="item.variableIsDisabled"
            />
          </el-form-item>
          <el-form-item
            v-if="!item.isValue"
            :label="item.valueLabel ? item.valueLabel : '变量类型'"
            :prop="'input_variables.' + index + '.type'"
            :rules="[
              {
                required:
                  item.is_required === true || item.is_required === false ? item.is_required : true,
                message: '请选择变量类型',
                trigger: 'change'
              }
            ]"
          >
            <el-select v-model="item.type" style="width: 86px" @change="item.value = ''">
              <el-option
                v-for="item in InputVariableList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              />
            </el-select>
          </el-form-item>

          <el-form-item
            v-if="item.type === VariableTypeEnum.SELECTOR || item.isValue"
            style="margin-top: 30px; flex: 1"
            :style="{ marginTop: item.isValue ? '0' : '30px' }"
            :prop="'input_variables.' + index + '.value'"
            :label="item.isValue ? item.valueLabel : ''"
            :rules="{
              required:
                item.is_required === true || item.is_required === false ? item.is_required : true,
              message: '请选择',
              trigger: 'change'
            }"
          >
            <el-cascader
              popper-class="basic-input-cascader"
              :popper-append-to-body="false"
              :options="variableList"
              :props="cascaderProps"
              v-model="item.value"
              @focus="getVariableList"
              @change="updateVariableType($event, item)"
            >
              <template #default="{ data }">
                <img :src="data.img" style="vertical-align: middle; margin-right: 5px" />
                <span>{{ data.label }}</span>
              </template>
            </el-cascader>
          </el-form-item>
          <el-form-item
            v-if="item.type === VariableTypeEnum.TEXT"
            style="margin-top: 30px; flex: 1"
            :prop="'input_variables.' + index + '.value'"
            :rules="{
              required:
                item.is_required === true || item.is_required === false ? item.is_required : true,
              message: '请输入',
              trigger: 'change'
            }"
          >
            <el-input v-model.trim="item.value" placeholder="请输入" />
          </el-form-item>
          <el-form-item
            v-if="item.isValue"
            style="flex: 1; margin-left: 6px"
            label="变量类型"
            :rules="{
              required:
                item.is_required === true || item.is_required === false ? item.is_required : true
            }"
          >
            {{ item.variableType }}
          </el-form-item>
          <el-form-item
            class="delete-btn mr-t-30"
            v-show="nodeDta.input_variables.length > 1 && isDeleteBtn"
          >
            <el-link
              :underline="false"
              class="fs-12"
              @click="nodeDta.input_variables.splice(index, 1)"
            >
              <el-icon><Delete /></el-icon>
            </el-link>
          </el-form-item>
        </template>
      </div>
    </el-form>
  </div>
</template>

<script setup lang="ts" name="BasicInputForm">
import { inject, nextTick, reactive, ref, watch } from 'vue';
import { RepeatValidator } from '@/utils/validate/validate';
import { FormRules } from 'element-plus';
import { Cell } from '@antv/x6';
import { isEmpty } from 'lodash-es';
import { workFlowStoreCounter } from '@/store/work-flow';
import { storeToRefs } from 'pinia';
import {
  InputVariableList,
  InputVariables,
  nanoId,
  NodeTypeEnum, OutputVariableTypeEnum,
  RepositoryNodeInputVariables,
  RepositoryOutVariables, StartNodeInputVariables, VariableTypeEnum
} from "@/view/graph/model/type";
import {NODES_MAP} from "@/view/graph/model/nodes";

const props = defineProps({
  title: {
    type: String,
    default: '输入'
  },
  isAddBtn: {
    type: Boolean,
    default: true
  },
  isDeleteBtn: {
    type: Boolean,
    default: true
  },
  isValue: {
    type: Boolean,
    default: false
  },
  formType: {
    type: String,
    default: 'other'
  },
  valueLabel: {
    type: String,
    default: ''
  }
});

const getNode = inject('getNode') as () => any;

const RuleFormRef = ref();

const repeatValidator = RepeatValidator;

const nodeDta = ref<{
  isInputFold: boolean;
  input_variables: RepositoryNodeInputVariables[];
}>({
  isInputFold: false,
  input_variables: [
    {
      ...InputVariables,
      uuId: nanoId()
    }
  ]
});

const variableList = ref<any>([]);

const rules = reactive<FormRules<RepositoryNodeInputVariables>>({
  variable: [{ required: true, message: '请输入参数名', trigger: 'change' }],
  type: [{ required: true, message: '请选择变量类型', trigger: 'change' }]
});
const workFlowStore = workFlowStoreCounter();
const { categoryGroupList } = storeToRefs(workFlowStore);
const cascaderProps = {
  checkStrictly: true
};

// watch(
//   () => NodeDataBus().nodeTime,
//   (newValue, oldValue) => {
//     if (newValue !== oldValue) {
//       getVariableList();
//     }
//   },
//   { immediate: true, deep: true }
// );

watch(
  nodeDta,
  newValue => {
    let obj = {
      ...getNode().getData(),
      isInputFold: newValue.isInputFold
    };
    if (getNode().shape === NodeTypeEnum.CHAT) {
      obj.config = newValue.input_variables;
    } else if ([NodeTypeEnum.END].includes(getNode().shape) || props.isValue) {
      obj.out_variables = newValue.input_variables;
    } else {
      obj.input_variables = newValue.input_variables;
    }
    getNode().setData(
      {
        ...getNode().getData(),
        ...obj,
        lastModify: new Date()
      },
      { overwrite: true }
    );
  },
  {
    deep: true
  }
);

/**
 * 数据初始化
 */
function init(formItem: { isInputFold: boolean; input_variables: RepositoryNodeInputVariables[] }) {
  nodeDta.value = formItem;
}

function recursionVariable(out_variables: RepositoryOutVariables[]) {
  const list: any = [];
  out_variables.forEach(item => {
    if ([NodeTypeEnum.ITERATION].includes(getNode().shape) && props.formType === 'iterationInput') {
      if (
        [
          OutputVariableTypeEnum.OBJECT,
          OutputVariableTypeEnum.ARRAY_OBJECT,
          OutputVariableTypeEnum.ARRAY_STRING,
          OutputVariableTypeEnum.ARRAY_NUMBER,
          OutputVariableTypeEnum.ARRAY_BOOLEAN,
          OutputVariableTypeEnum.ARRAY
        ].includes(item.type as OutputVariableTypeEnum)
      ) {
        list.push({
          value: item.id,
          label: item.variable,
          type: item.type,
          children: item.schema ? recursionVariable(item.schema) : []
        });
      }
    } else if (
      [OutputVariableTypeEnum.OBJECT, OutputVariableTypeEnum.ARRAY_OBJECT].includes(
        item.type as OutputVariableTypeEnum
      )
    ) {
      list.push({
        value: item.id,
        label: item.variable,
        type: item.type,
        children: item.schema ? recursionVariable(item.schema) : []
      });
    } else {
      list.push({
        value: item.id,
        label: item.variable,
        type: item.type,
        children: []
      });
    }
  });
  return list;
}

// 定义递归函数来判断 value 是否在 children 中
function checkIfValueExistsInChildren(value: string, children: any) {
  for (const child of children) {
    if (child.value === value) {
      return true;
    }
    // 如果该 child 有 children 列表，则递归检查
    if (child.children && child.children.length > 0) {
      if (checkIfValueExistsInChildren(value, child.children)) {
        return true;
      }
    }
  }
  return false;
}

// 定义函数检查 list 中最后一项是否存在于 str 中的任何层级的 children
function checkIfLastValueExistsInNestedChildren(lastValue: string) {
  for (const item of variableList.value) {
    if (checkIfValueExistsInChildren(lastValue, item.children)) {
      return true;
    }
  }
  return false;
}

function constructList(list: any) {
  const categoryList = categoryGroupList.value.map(item => item.children).flat();
  const parent = getNode().parent;
  const graph = getNode()?.model?.graph;
  const cell = graph?.getCellById(parent?.id);
  let incomNode: any;
  if (cell && graph) {
    incomNode = graph?.getNeighbors(cell, { incoming: true, outgoing: false })?.[0] as any;
  }
  list?.forEach((item: Cell) => {
    const id = item.id;
    const data = item.getData();
    const { title, input_variables = [], out_variables = [] } = data || {};
    if (!isEmpty(input_variables) || !isEmpty(out_variables)) {
      let children = [];
      if (item.shape === NODES_MAP.START) {
        children = input_variables
          ?.map((item: StartNodeInputVariables) => {
            if ([NodeTypeEnum.ITERATION].includes(getNode().shape)) {
              if (VariableTypeEnum.OBJECT === item?.type) {
                return {
                  value: item.id,
                  label: item.label,
                  type: item.type
                };
              }
            } else {
              return {
                value: item.id,
                label: item.label,
                type: item.type
              };
            }
          })
          ?.filter((item: any) => item !== undefined);
      } else if (incomNode?.id === id) {
        children = recursionVariable(input_variables);
      } else {
        children = recursionVariable(out_variables);
      }
      if (children?.length > 0) {
        variableList.value.unshift({
          value: id,
          label: title,
          shape: item.shape,
          img: categoryList.find(el => el.code === item.shape)?.img,
          disabled: true,
          children: children
        });
      }
    }
  });
}

/**
 * 获取可用变量
 */
function getVariableList() {
  const graph = getNode()?.model?.graph;
  variableList.value = [];
  if (props.formType === 'iterationOut') {
    const outNode = graph?.getNeighbors(getNode(), { incoming: false, outgoing: true })?.[0] as any;
    constructList(outNode?.children);
  } else {
    const list = graph?.getPredecessors(getNode());
    constructList(list);
  }

  nextTick(() => {
    nodeDta.value.input_variables.forEach((item: RepositoryNodeInputVariables) => {
      if (item.type === 'selector' && !isEmpty(item.value)) {
        const secondValue = item.value[item.value.length - 1];
        const existsInProList = checkIfLastValueExistsInNestedChildren(secondValue);
        if (!existsInProList) {
          item.value = [];
        }
      }
    });
    console.log(variableList.value);
  });
}

/**
 * 添加变量
 */
function addInputVariable() {
  nodeDta.value.input_variables.push({
    ...InputVariables,
    isValue: props.isValue,
    valueLabel: props.valueLabel ? props.valueLabel : props.isValue ? '变量取值' : '',
    uuId: nanoId(),
    id: nanoId()
  });
  console.log(nodeDta.value.input_variables);
}

/**
 * form表单校验
 */
const submitForm = async () => {
  if (!RuleFormRef.value) return false;
  return new Promise<boolean>(resolve => {
    RuleFormRef.value.validate((valid: boolean) => {
      resolve(valid);
    });
  });
};

/**
 * 通过 value 值查找匹配的节点
 * @param list
 * @param value
 */
function findLastNodeType(list: any[], value: string[]): string {
  let matchedNodeType = '';

  // 遍历整个节点列表
  for (let item of list) {
    // 如果当前节点的 value 匹配 value 数组中的任意项，更新 matchedNodeType
    if (value.includes(item.value)) {
      matchedNodeType = item.type;
    }

    // 如果当前节点有 children，则递归查找子节点中的匹配项
    if (item.children && item.children.length > 0) {
      const childMatchedNodeType = findLastNodeType(item.children, value);
      // 如果子节点有匹配项，更新 matchedNodeType
      if (childMatchedNodeType) {
        matchedNodeType = childMatchedNodeType;
      }
    }
  }

  // 返回最后匹配的节点的 type
  return matchedNodeType;
}

/**
 * 更新变量类型
 * @param event
 * @param item
 */
function updateVariableType(event: string[], item: RepositoryNodeInputVariables) {
  if (props.isValue) {
    item.variableType = findLastNodeType(variableList.value, event);
  }
}

defineExpose({
  init,
  submitForm,
  variableList
});
</script>

<style scoped lang="scss">
.form-box {
  display: flex;
}
.delete-btn {
  display: flex;
  margin-left: 14px;
}
</style>
